package com.borrowed.book.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.borrowed.book.config.shiro.WeChatToken;
import com.borrowed.book.system.domain.*;
import com.borrowed.book.system.service.ISysDictService;
import com.borrowed.book.system.service.SystemLoginService;
import com.borrowed.book.system.util.HttpUtil;
import com.borrowed.book.system.util.StringUtils;
import com.borrowed.book.user.domain.SUser;
import io.swagger.annotations.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 登录验证
 * @author jinbin
 */
@RestController
@Api(tags = "系统管理")
@RequestMapping("/api")
public class SysLoginController {
    public static final Logger log = LoggerFactory.getLogger(com.borrowed.book.system.controller.SysLoginController.class);

    @Value("${book.image.fileOriPath}")
    private  String fileOriPath;//附件上传路径
    @Value("${book.image.fileOrmPath}")
    private String fileOrmPath;//文件获取映射路径

    @Value("${weixin.appId}")
    private String appId;
    @Value("${weixin.appSecret}")
    private String appSecret;

    @Autowired
    private ISysDictService dictService;
    @Autowired
    private SystemLoginService loginService;

    @ApiOperation(value = "后台登录", notes = "后台登录", httpMethod = "POST")
    @PostMapping("/login")
    @ResponseBody
    public AjaxResult login(@RequestBody SysLoginDto sysLoginDto, HttpServletRequest request){
        //账号密码验证
        UsernamePasswordToken token=new UsernamePasswordToken(sysLoginDto.getUsername(),sysLoginDto.getPassword());
        Subject subject= SecurityUtils.getSubject();
        //token信息
        Serializable tokenId = subject.getSession().getId();
        try {
            subject.login(token);
            return AjaxResult.sucess("登录成功",tokenId);
        }catch (UnknownAccountException e){
            String msg="用户或者密码不正确";
            if(StringUtils.isNotEmpty(e.getMessage())){
                msg=e.getMessage();
            }
            return AjaxResult.error(msg);
        }
    }


    @ApiOperation(value = "后台退出", notes = "后台退出", httpMethod = "GET")
    @GetMapping("/logout")
    public AjaxResult logout() {
        //在这里执行退出系统前需要清空的数据
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()) {
            subject.logout();
        }
        return AjaxResult.sucess("退出成功");
    }


    @ApiOperation(value = "数据字典根据类型获取", notes = "数据字典根据类型获取,不传则获取所有数据字典值", httpMethod = "GET")
    @ApiImplicitParam(name="typeCode",value = "数据字典类型code")
    @GetMapping("/getDictByType")
    public AjaxResult getDictByDictType(String typeCode){
        if(StringUtils.isEmpty(typeCode)){
            List<SysDictTypePojo> allDictList=dictService.getAllDictList();
            return AjaxResult.sucess("查询成功",allDictList);
        }else {
            List<SysDictPojo> dictList = dictService.getDictByType(typeCode);
            return AjaxResult.sucess("查询成功", dictList);
        }
    }

    @ApiOperation(value = "附件上传", notes = "附件上传", httpMethod = "POST")
    @ApiImplicitParam(name="file",value = "附件上传",dataType = "__file",paramType = "form")
    @PostMapping("/uploadFile")
    @ResponseBody
    public UpFileResult uploadSingleImage(MultipartFile file){
        UpFileResult upFileResult=new UpFileResult();
        try{
            if(file.isEmpty()){
                upFileResult.setErrno(1);
                return upFileResult;
            }
            String fileName=file.getOriginalFilename();
            String fileType=fileName.substring(fileName.lastIndexOf("."),fileName.length());
            String uuidStr=GetUUidStr();
            //文件真实存储路径
            String extraFileName= fileOriPath+"/"+GetDateStr()+"/"+uuidStr+fileType;
            //映射虚拟路径
            String ormUrl=fileOrmPath+"/"+GetDateStr()+"/"+uuidStr+fileType;
            File dest=new File(extraFileName);
            if(!dest.getParentFile().exists()){
                dest.getParentFile().mkdirs();
            }
            file.transferTo(dest);
            upFileResult.setErrno(0);
            List<String> data=new ArrayList<>();
            data.add(extraFileName);

            upFileResult.setUrl(ormUrl);
            upFileResult.setData(data);
        }catch (Exception e){
            e.printStackTrace();
            log.error("文件上传失败："+file.getOriginalFilename());
        }
        return upFileResult;
    }


    @ApiOperation(value = "微信登录", notes = "微信小程序登录", httpMethod = "POST")
    @ApiImplicitParam(name="code",value = "wx.login()返回的code",dataType = "String")
    @PostMapping("/wxLogin")
    @ResponseBody
    @Transactional
    public AjaxResult wxLogin(HttpServletRequest request,String code){
        try {
            WxLoginOutDto loginOutDto=loginService.getWxLoginInfo(code, appId, appSecret);
            if(loginOutDto==null){
                return AjaxResult.error("认证获取openid失败，认证失败");
            }else{
                Subject subject= SecurityUtils.getSubject();
                //token信息
                Serializable tokenId = subject.getSession().getId();
                subject.login(new WeChatToken(loginOutDto.getOpenId(),loginOutDto.getSessionKey()));
                SUser sysUser = (SUser) SecurityUtils.getSubject().getPrincipal();
                sysUser.setTokenId(tokenId);
                return AjaxResult.sucess("登录成功",sysUser);
            }
        }catch (Exception e){
            e.printStackTrace();
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation(value = "微信手机号码获取", notes = "getPhoneNumber获取到的值进行解析，（后面是否再更新到用户表里待定）", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name="encryptedData",value = "包括敏感数据在内的完整用户信息的加密数据",dataType = "String")
                      ,@ApiImplicitParam(name="iv",value = "加密算法的初始向量",dataType = "String")})
    @PostMapping("/wxPhoneNumber")
    @ResponseBody
    public AjaxResult wxPhoneNumber(String encryptedData,String iv){
        AjaxResult result;
        try{
            String phoneNum=loginService.getPhoneNumber(encryptedData,iv);
            result=AjaxResult.sucess(phoneNum);
        }catch (Exception e){
            e.printStackTrace();
            result=AjaxResult.error(e.getMessage());
        }
        return result;
    }

    /**
     * 获取当前时间串，用于文件存储路径使用
     * @return
     */
    public String GetDateStr(){
        Date date=new Date();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd");
        String dateStr=sdf.format(date);
        return dateStr;
    }

    /**
     * 获取UUID随机串，上传文件使用
     * @return
     */
    public String GetUUidStr(){
        String uuidStr= UUID.randomUUID().toString();
        return uuidStr;
    }
}
